import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import tailwindcss from '@tailwindcss/vite'
import { minify } from 'csso'

/**
 * 修复普通字符串
 * @param {*} str
 */
function fixClass(str) {
    return str.replace(/[^a-zA-Z0-9-_ ]/g, '_')
}

/**
 * 修复尖引号括起来的字符串
 * @param {string} str
 */
function fixSharpQuote(str) {
    return str.replace(/< (.+?) >/g, (_, $1) => {
        return fixClass($1)
    })
}

const remPx = 16
export default defineConfig({
    plugins: [
        uni.default(),
        tailwindcss(),
        {
            name: 'fixclass',
            enforce: 'pre',
            transform(code, id) {
                if (id.endsWith('App.uvue?vue&type=style&index=0&lang.css') || id.endsWith('App.uvue?vue&type=style&index=0&inline&lang.css')) {
                    code = minify(code, { restructure: false }).css//Web端需要主动压缩一下
                    const propertiesStr = code.match(/:root,:host\{(.+?)\}/)[1]
                    const propertieMap = new Map(propertiesStr.split(';').filter(Boolean).map(a => a.split(':')))
                    const newCode = code
                        .replace(/\/\*.+?\*\/\s*/, '')
                        .replace('@layer properties;', '')
                        .replace(/@layer properties.+?@supports.+?\}\}\}/, '')
                        .replace(/@property.+?\}/g, '')
                        .replace(/\.transition\{.+?\}/, '')
                        .replace(/\.transform\{.+?\}/, '')
                        .replace(/:root,:host.+?\}/, '')
                        .replace(/(\.)(.+?)(\{)/g, (_, $1, $2, $3) => {
                            return $1 + $2.replace(/\\./g, '_') + $3
                        })//修正选择器，替换App不支持的字符为_
                        .replace(/3\.40282e38px/g, '10000px')//Web端rounded-full
                        .replace(/calc\(infinity.+?\)/g, '10000px')//H5端rounded-full
                        .replace(/var\(\-\-tw[^\)]+?,(var\(\-\-.+?\))\)/g, '$1')//var(--tw-leading, var(--text-base--line-height)) 转换为 var(--text-base--line-height)
                        .replace(/var\(\-\-tw[^\)]+?,(.+?)\)/g, '$1')//var(--tw-shadow-color, #62c6ed66) 转换为 #62c6ed66
                        .replace(/\-\-tw\-shadow:(.+?);box\-shadow:.+?\}/g, 'box-shadow:$1}')//处理box-shadow，不要使用变量，而是直接把值给box-shadow属性
                        .replace(/var\((.+?)\)/g, (_, $1) => propertieMap.get($1) ?? _)//var(--text-base--line-height) 转换为 calc(1.5 / 1)
                        .replace(/((\d+|\.\d+|\d+\.\d+))rem/g, (_, $1) => Number($1) * remPx + 'px')//rem转px
                        .replace(/calc\((.+?)\)/g, (_, $1) => {
                            if ($1.includes('px')) {
                                const [l, r] = $1.split('px*').map(Number)
                                return `${l * r}px`
                            } else if ($1.includes('/')) {
                                const [l, r] = $1.split('/').map(Number)
                                return `${l / r}`
                            }
                        })
                        .replace(/translate\((.+?)\)/g, 'translateX($1)')
                        .replace(/(linear\-gradient\()(0deg)/g, '$1to top')
                        .replace(/(linear\-gradient\()(45deg)/g, '$1to top right')
                        .replace(/(linear\-gradient\()(90deg)/g, '$1to right')
                        .replace(/(linear\-gradient\()(135deg)/g, '$1to bottom right')
                        .replace(/(linear\-gradient\()(180deg)/g, '$1to bottom')
                        .replace(/(linear\-gradient\()(225deg)/g, '$1to bottom left')
                        .replace(/(linear\-gradient\()(270deg)/g, '$1to left')
                        .replace(/(linear\-gradient\()(315deg)/g, '$1to top left')
                        .replace(/((margin|padding))\-inline.+?(\d+(px)?)(;?)/g, '$1-left:$3;$1-right:$3')
                        .replace(/((margin|padding))\-block.+?(\d+(px)?)(;?)/g, '$1-top:$3;$1-bottom:$3')
                    return { code: newCode, map: null }
                }
                if (id.endsWith('.uvue')) {
                    const newCode = code.replace(/([^:]class=")(.*?)(")/gs, (_, $1, $2, $3) => {
                        return $1 + fixClass($2) + $3
                    }).replace(/(:class=")(.+?)(")/gs, (_, $1, $2, $3) => {
                        return $1 + fixSharpQuote($2) + $3
                    })
                    return { code: newCode, map: null }
                }
            },
        },
    ]
})
